/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "SnapshotDelete.h"
#include "log/Log.h"

using namespace std;
using namespace Module;
namespace {
    const auto MODULE = "SnapshotDelete";
    constexpr int NUMBER100 = 100;
}


SnapshotDelete::~SnapshotDelete() {}


int SnapshotDelete::PrerequisiteJob()
{
    return Module::SUCCESS;
}

int SnapshotDelete::PostJob()
{
    return Module::SUCCESS;
}

int SnapshotDelete::GenerateSubJob()
{
    m_jobInfoPtr = dynamic_pointer_cast<AppProtect::DelCopyJob>(m_jobCommonInfo->GetJobInfo());
    m_jobId = m_jobInfoPtr->jobId;
    int ret = GenerateSubJobInner();
    if (ret == Module::FAILED) {
        ReportJobDetails("plugin_generate_subjob_fail_label",
            JobLogLevel::type::TASK_LOG_ERROR, SubJobStatus::FAILED, m_jobProgress);
        HCP_Log(ERR, MODULE) << "Delete GenerateSubJob failed,jobId is: " << m_jobInfoPtr->jobId << HCPENDLOG;
    }
    SetJobToFinish();
    return ret;
}

int SnapshotDelete::GenerateSubJobInner()
{
    HCP_Log(INFO, MODULE) << "Generate sub task, task id is " << m_jobId << HCPENDLOG;
    SubJob subJob;
    subJob.__set_jobId(m_jobId);
    subJob.__set_jobType(SubJobType::BUSINESS_SUB_JOB);
    subJob.__set_jobName("SnapshotDelete");
    subJob.__set_policy(ExecutePolicy::ANY_NODE); // LOCAL_NODE
    std::vector<SubJob> vec;
    vec.push_back(subJob);
    ActionResult result;

    JobService::AddNewJob(result, vec);
    if (result.code == Module::FAILED) {
        HCP_Log(INFO, MODULE) << "Finish to generate sub job, main task id is " << m_jobId << HCPENDLOG;
        return Module::FAILED;
    }
    ReportJobDetails(EMPTY_LABEL,
        JobLogLevel::type::TASK_LOG_INFO, SubJobStatus::COMPLETED, NUMBER100);
    HCP_Log(INFO, MODULE) << "Success to generate sub job, main task id is " << m_jobId << HCPENDLOG;
    return Module::SUCCESS;
}

int SnapshotDelete::ExecuteSubJob()
{
    m_jobInfoPtr = dynamic_pointer_cast<AppProtect::DelCopyJob>(m_jobCommonInfo->GetJobInfo());
    m_subjobId = m_subJobInfo->subJobId;
    m_jobId = m_subJobInfo->jobId;
    int ret = ExecuteSubJobInner();
    if (ret == Module::FAILED) {
        ReportJobDetails("plugin_backup_subjob_fail_label",
            JobLogLevel::type::TASK_LOG_ERROR, SubJobStatus::FAILED, m_jobProgress);
        HCP_Log(ERR, MODULE) << "Snapshot Delete failed jobId: " << m_jobId <<
            " subjobid is:" << m_subjobId << HCPENDLOG;
    }
    SetJobToFinish();
    return ret;
}

int SnapshotDelete::ExecuteSubJobInner()
{
    HCP_Log(INFO, MODULE) << "Start to Execute DelCopy ExecuteSubJob, jobid: " << m_jobId << ",  subjobid: " <<
        m_subjobId << HCPENDLOG;
    ActionResult result;
    SubJobDetails subJobDetails;
    LogDetail logDetail{};
    std::vector<LogDetail> logDetailList;

    if (InitJobInfo() != Module::SUCCESS) {
        HCP_Log(ERR, MODULE) << "Init Job info fail, main task id is " << m_parentJobId << HCPENDLOG;
        return Module::FAILED;
    }

    if (InitDeviceInfo() != Module::SUCCESS) {
        HCP_Log(ERR, MODULE) << "Init device info fail, main task id is " << m_parentJobId << HCPENDLOG;
        return Module::FAILED;
    }

    if (IsAbortJob()) {
        ReportJobDetails(EMPTY_LABEL,
            JobLogLevel::type::TASK_LOG_WARNING, SubJobStatus::ABORTED, m_jobProgress);
        return Module::FAILED;
    }
    int ret = ExecuteSnapshotDelete();
    if (ret != Module::SUCCESS) {
        AddLogDetail(logDetail, "nas_plugin_snapshot_delete_fail_label", JobLogLevel::TASK_LOG_ERROR);
        AddErrCode(logDetail, ret);
        REPORT_LOG2AGENT(subJobDetails, result, logDetailList, logDetail, m_curProcess, 0, SubJobStatus::FAILED);
        return Module::FAILED;
    }
    ReportJobDetails(EMPTY_LABEL, JobLogLevel::type::TASK_LOG_INFO, SubJobStatus::COMPLETED, NUMBER100);
    return Module::SUCCESS;
}

int SnapshotDelete::ExecuteSnapshotDelete()
{
    HCP_Log(INFO, MODULE) << "Start to perform snapshot delete,"
        << " snapshot name - " << m_snapshotName
        << " snapshot id - " << m_snapshotId
        << HCPENDLOG;
    m_localDeviceController->SetRetryAttr(1);

    int ret = Module::FAILED;
    if (GetVendorType(m_nasHost.vendorSubType) == Module::STORAGE_ENUM::DORADO) {
        auto localDeviceControl = dynamic_pointer_cast<Module::DoradoNas>(m_localDeviceController);
        ret = localDeviceControl->DeleteSnapshotWithVstoreId(m_snapshotName, m_snapshotId, m_vstoreId);
    }
    if (GetVendorType(m_nasHost.vendorSubType) == Module::STORAGE_ENUM::FUSIONSTORAGE) {
        auto localDeviceControl = dynamic_pointer_cast<Module::FusionStorageNas>(m_localDeviceController);
        ret = localDeviceControl->DeleteSnapshot(m_snapshotName);
    }
    if (ret != Module::SUCCESS) {
        HCP_Log(ERR, MODULE) << "Failed to perform snapshot delete. the name of snapshotId is: "
            << m_snapshotId << HCPENDLOG;
        return ret;
    }

    HCP_Log(INFO, MODULE) << "the Snapshot has deleted" << HCPENDLOG;

    return Module::SUCCESS;
}

int SnapshotDelete::InitJobInfo()
{
    m_deviceInfo.username = m_jobInfoPtr->protectEnv.auth.authkey;
    m_deviceInfo.password = m_jobInfoPtr->protectEnv.auth.authPwd;
    m_deviceInfo.port = std::to_string(m_jobInfoPtr->protectEnv.port);
    m_deviceInfo.fileSystemName = m_jobInfoPtr->protectEnv.name;
    m_deviceInfo.ipList = m_jobInfoPtr->protectEnv.endpoint;

    Json::Reader jsonReader;
    Json::Value extendInfoCopyJson;
    if (!jsonReader.parse(m_jobInfoPtr->copies[0].extendInfo, extendInfoCopyJson)) {
        HCP_Log(ERR, MODULE) << "ProtectObjectExtendInfo is invaild." << HCPENDLOG;
        return Module::FAILED;
    }
    if (extendInfoCopyJson.isObject() && extendInfoCopyJson.isMember("snapshotId") &&
        extendInfoCopyJson["snapshotId"].isString()) {
        m_snapshotId = extendInfoCopyJson["snapshotId"].asString();
    }
    if (extendInfoCopyJson.isObject() && extendInfoCopyJson.isMember("snapshotName") &&
        extendInfoCopyJson["snapshotName"].isString()) {
        m_snapshotName = extendInfoCopyJson["snapshotName"].asString();
    }

    ProtectObjectExtendInfo extendInfo {};
    if (!JsonHelper::JsonStringToStruct(m_jobInfoPtr->protectObject.extendInfo, extendInfo)) {
        HCP_Log(ERR, MODULE) << "ProtectObjectExtendInfo is invaild." << HCPENDLOG;
        return Module::FAILED;
    }
    m_deviceInfo.fileSystemId = extendInfo.fileSystemId;
    m_vstoreId = extendInfo.tenantId;

    HCP_Log(INFO, MODULE) << "m_deviceInfo.username: " << m_deviceInfo.username << HCPENDLOG;
    HCP_Log(INFO, MODULE) << "m_deviceInfo.port: " << m_deviceInfo.port << HCPENDLOG;
    HCP_Log(INFO, MODULE) << "m_deviceInfo.fileSystemName: " << m_deviceInfo.fileSystemName << HCPENDLOG;
    HCP_Log(INFO, MODULE) << "m_deviceInfo.ipList: " << m_deviceInfo.ipList << HCPENDLOG;
    HCP_Log(INFO, MODULE) << "m_deviceInfo.fileSystemId: " << m_deviceInfo.fileSystemId << HCPENDLOG;
    HCP_Log(INFO, MODULE) << "Snapshot Id: " << m_snapshotId << HCPENDLOG;

    m_nasHost.vendorSubType = m_jobInfoPtr->protectEnv.subType;

    return Module::SUCCESS;
}